/* registergraph.cpp
 * Class RegisterGraph inherits QWidget (used as an MDI subwindow)
 * Class for the register graph subwindows
 * The actual plot widget is added in code, not in the .ui file
 * Handles the creation and deletion of plot items as well as the updates
 */

#include <QLayout>
#include <QLineEdit>
#include <QTimer>
#include <QDropEvent>
#include <QDateTime>
#include <QDebug>

#include "registerplot.h"
#include "registerdef.h"

#include "registergraph.h"
#include "ui_registergraph.h"

RegisterGraph::RegisterGraph(QWidget *parent) :
    QWidget(parent),
    m_ui(new Ui::RegisterGraph)
{
    m_ui->setupUi(this);

    updateInterval = 1000;
    maxSamples = 1000;

    registerList = 0;
    graphedRegisters = QList<int>();

    //This ensures that we don't leak memory when a graph window is closed
    setAttribute(Qt::WA_DeleteOnClose);
    setAcceptDrops(true);

    //Add a register plot with a default update interval of 1 sec
    ui_plot = new RegisterPlot(1000, this);
    ui_plot->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
    ui_plot->setMinimumSize(300, 300);

    ui_interval = qFindChild<QLineEdit*>(this, "lineEdit");
    ui_interval->setText(QString::number(updateInterval));

    ui_layout = qFindChild<QVBoxLayout*>(this, "verticalLayout");
    ui_layout->addWidget(ui_plot);

    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateData()));

    connect(ui_plot, SIGNAL(legendClicked(QwtPlotItem*)), this, SLOT(removeCurve(QwtPlotItem*)));

    //Should really be static const but oh well
    colors << QColor(Qt::red) << QColor(Qt::blue) << QColor(Qt::green) << QColor(Qt::yellow) << QColor(Qt::white) << QColor(Qt::black);
}

RegisterGraph::~RegisterGraph()
{
    delete m_ui;
}

void RegisterGraph::changeEvent(QEvent *e)
{
    //Qt designer created this, just leave it
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void RegisterGraph::updateData()
{
    //Called from timer signal; first figure out the length of time we've been graphing
    // queue a read for the relevant registers and then add the current values to the plot
    if (!graphedRegisters.isEmpty()) {
        int graphedSeconds = (int)ceil(updateInterval * ((double)ui_plot->count()+5)  / 1000);
        //int graphedSeconds = (int)ceil((updateInterval * (double)maxSamples) / 1000);
        QTime time = QTime::currentTime();
        double currentTime = ((double)time.hour()/24) + ((double)time.minute()/(24*60)) + ((double)time.second()/(24*60*60));
        QTime sTime = time.addSecs(-graphedSeconds);
        double startTime = ((double)sTime.hour()/24) + ((double)sTime.minute()/(24*60)) + ((double)sTime.second()/(24*60*60));
        for (register int i=0; i < graphedRegisters.count(); ++i) {
            int regAddress = graphedRegisters.at(i);
            emit readNeeded(regAddress);
            RegisterDef reg = registerList->at(registerList->indexOf(RegisterDef(regAddress)));
            ui_plot->appendData(currentTime, reg.getfValue(), i);
            ui_plot->setAxisScale(2, startTime, currentTime);
            ui_plot->replot();
        }
    }
}

void RegisterGraph::setRegisterList(QList<RegisterDef>* regList)
{
    registerList = regList;
}

void RegisterGraph::start()
{
    timer->start(updateInterval);
}

void RegisterGraph::stop()
{
    timer->stop();
}

void RegisterGraph::on_lineEdit_editingFinished()
{
    if (ui_interval->text().toInt() > 500) {
        updateInterval = ui_interval->text().toInt();
        timer->stop();
        timer->start(updateInterval);
    }
    ui_interval->setText(QString::number(updateInterval));
}

void RegisterGraph::dragEnterEvent(QDragEnterEvent *event)
 {
    event->acceptProposedAction();
 }

void RegisterGraph::dropEvent(QDropEvent *event)
{
    //The data we receive on a drag and drop event is a list of register names
    // look up the names in the register list and add them to the plot
    event->acceptProposedAction();
    QByteArray encodedData = event->mimeData()->data("application/vnd.text.list");
    QDataStream stream(&encodedData, QIODevice::ReadOnly);
    QStringList newItems;

    while (!stream.atEnd()) {
     QString text;
     stream >> text;
     newItems << text;
    }

    qDebug() << "Decoded dropped data as " << newItems;
    
    foreach (QString regName, newItems) {
        RegisterDef reg = RegisterDef(regName);
        if (registerList->contains(reg)) {
            reg = registerList->at(registerList->indexOf(reg));
            addRegister(reg);
        }
    }
}

void RegisterGraph::addRegister(RegisterDef reg)
{
    //Cycle through the list of colors as we add curves
    QColor color = colors.takeFirst();
    graphedRegisters.append(reg.address());
    ui_plot->addCurve(reg.name().toAscii(), color);
    colors.append(color);
}

void RegisterGraph::removeCurve(QwtPlotItem* item)
{
    //When the user clicks on a register name, find it in our list based on its name
    // remove it from our list and from the plot
    QString curveName = item->title().text();
    foreach (int regAddress, graphedRegisters) {
         QString regName = registerList->at(registerList->indexOf(RegisterDef(regAddress))).name();
         if (curveName == regName) {
             ui_plot->removeCurve(item);
             graphedRegisters.removeAll(regAddress);
             ui_plot->replot();
             break;
         }
    }
}
